{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d71dc818-3b16-4d8f-8a03-9ca7a3f03d15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]]\n"
     ]
    }
   ],
   "source": [
    "# 2D Wavelet Packets\n",
    "from __future__ import print_function\n",
    "import pywt\n",
    "import numpy\n",
    "x = numpy.array([[1, 2, 3, 4, 5, 6, 7, 8]] * 8, 'd')\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "65335f18-047f-47d3-84ed-d88cb3ef8dad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]]\n",
      "''\n",
      "0\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "# Now create a 2D Wavelet Packet object:\n",
    "wp = pywt.WaveletPacket2D(data=x, wavelet='db1', mode='symmetric')\n",
    "# The input data and decomposition coefficients are stored in the WaveletPacket2D.data attribute:\n",
    "print(wp.data)\n",
    "print(repr(wp.path))\n",
    "print(wp.level)\n",
    "print(wp.maxlevel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "442f3314-0c76-4a90-b4d2-f4e87f606c72",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]]\n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n",
      "[[-1. -1. -1. -1.]\n",
      " [-1. -1. -1. -1.]\n",
      " [-1. -1. -1. -1.]\n",
      " [-1. -1. -1. -1.]]\n",
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "# Traversing WP tree\n",
    "# Wavelet Packet nodes are arranged in a tree. Each node in a WP tree is uniquely identified and addressed by a path string.\n",
    "\n",
    "# In the 1D WaveletPacket case nodes were accessed using 'a' (approximation) and 'd' (details) path names (each node has two 1D children).\n",
    "\n",
    "# Because now we deal with a bit more complex structure (each node has four children), we have four basic path names based on the dwt 2D output convention to address the WP2D structure:\n",
    "\n",
    "#         a - LL, low-low coefficients\n",
    "#         h - LH, low-high coefficients\n",
    "#         v - HL, high-low coefficients\n",
    "#         d - HH, high-high coefficients\n",
    "\n",
    "# In other words, subnode naming corresponds to the dwt2() function output naming convention (as wavelet packet transform is based on the dwt2 transform):\n",
    "\n",
    "#                             -------------------\n",
    "#                             |        |        |\n",
    "#                             | cA(LL) | cH(LH) |\n",
    "#                             |        |        |\n",
    "# (cA, (cH, cV, cD))  <--->   -------------------\n",
    "#                             |        |        |\n",
    "#                             | cV(HL) | cD(HH) |\n",
    "#                             |        |        |\n",
    "#                             -------------------\n",
    "\n",
    "#    (fig.1: DWT 2D output and interpretation)\n",
    "\n",
    "# Knowing what the nodes names are, we can now access them using the indexing operator obj[x] (WaveletPacket2D.__getitem__()):\n",
    "print(wp['a'].data)\n",
    "print(wp['h'].data)\n",
    "print(wp['v'].data)\n",
    "print(wp['d'].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "5469215b-260c-4af0-bb69-9ee7958f3b42",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[10. 26.]\n",
      " [10. 26.]]\n"
     ]
    }
   ],
   "source": [
    "print(wp['aa'].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "65e2d18e-c110-45e9-a2dc-5cfcd3b1ecfd",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[10. 26.]\n",
      " [10. 26.]]\n",
      "True\n"
     ]
    }
   ],
   "source": [
    "node = wp['a']\n",
    "print(node['a'].data)\n",
    "print(wp['a']['a'].data is wp['aa'].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "106efcda-5eae-4948-9db3-c28a406fcdab",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[36.]]\n"
     ]
    },
    {
     "ename": "IndexError",
     "evalue": "Path length is out of range.",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mIndexError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[0;32m/tmp/ipykernel_47156/518126128.py\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m      1\u001b[0m \u001b[0;31m# Following down the decomposition path:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      2\u001b[0m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'aaa'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mwp\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'aaaa'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
      "\u001b[0;32m/usr/local/lib/python3.8/dist-packages/pywt/_wavelet_packets.py\u001b[0m in \u001b[0;36m__getitem__\u001b[0;34m(self, path)\u001b[0m\n\u001b[1;32m    262\u001b[0m             if (self.maxlevel is not None and\n\u001b[1;32m    263\u001b[0m                     len(path) > self.maxlevel * self.PART_LEN):\n\u001b[0;32m--> 264\u001b[0;31m                 \u001b[0;32mraise\u001b[0m \u001b[0mIndexError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"Path length is out of range.\"\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m    265\u001b[0m             \u001b[0;32mif\u001b[0m \u001b[0mpath\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m    266\u001b[0m                 return self.get_subnode(path[0:self.PART_LEN], True)[\n",
      "\u001b[0;31mIndexError\u001b[0m: Path length is out of range."
     ]
    }
   ],
   "source": [
    "# Following down the decomposition path:\n",
    "print(wp['aaa'].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "8c463d4a-0491-4d77-aa59-9002e40eb8a3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    " print(wp.maxlevel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "aa520f74-4211-4cd1-97bc-ff2961cdccdf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[-4. -4.]\n",
      " [-4. -4.]]\n"
     ]
    }
   ],
   "source": [
    "# Accessing Node2D’s attributes\n",
    "# WaveletPacket2D is a tree data structure, which evaluates to a set of Node2D objects. WaveletPacket2D is just a special subclass of the Node2D class (which in turn inherits from a BaseNode, just like with Node and WaveletPacket for the 1D case.).\n",
    "print(wp['av'].data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "0938e934-1792-41dc-a0c7-df2dd1bb9991",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "av\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "c3dbc818-be06-4fa7-807a-6c6ba00d4cca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "v\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].node_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "68a6758f-0b73-4a5c-8233-9e33a8c95421",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].parent.path)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "592b668e-6ddc-430e-aec7-9657f418acb8",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]]\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].parent.data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "239b8147-895b-47df-a0ed-d72c9dda03f2",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].level)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "f8af0dd6-ab38-46c1-bc52-a5dd4d6473cc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].maxlevel)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "18e4d4fc-15f0-4d30-b5fe-afd3d74b199f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "symmetric\n"
     ]
    }
   ],
   "source": [
    "print(wp['av'].mode)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "7fb28f67-e936-4962-910f-bcd57ff80f2c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['']\n"
     ]
    }
   ],
   "source": [
    "# Collecting nodes\n",
    "# 0 level - the root wp node:\n",
    "len(wp.get_level(0))\n",
    "print([node.path for node in wp.get_level(0)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "aa795e40-f4eb-4c74-a8fa-e034c2126a53",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'h', 'v', 'd']\n"
     ]
    }
   ],
   "source": [
    "# 1st level of decomposition:\n",
    "len(wp.get_level(1))\n",
    "print([node.path for node in wp.get_level(1)])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "83d8ac48-397c-4a9a-9d04-70a711bca952",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "aa ah av ad\n",
      "ha hh hv hd\n",
      "va vh vv vd\n",
      "da dh dv dd\n"
     ]
    }
   ],
   "source": [
    "# 2nd level of decomposition:\n",
    "len(wp.get_level(2))\n",
    "paths = [node.path for node in wp.get_level(2)]\n",
    "for i, path in enumerate(paths):\n",
    "    if (i+1) % 4 == 0:\n",
    "        print(path)\n",
    "    else:\n",
    "        print(path, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "2d95e1c4-3633-4054-83b0-62667887203f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "64\n",
      "aaa aah aav aad aha ahh ahv ahd\n",
      "ava avh avv avd ada adh adv add\n",
      "haa hah hav had hha hhh hhv hhd\n",
      "hva hvh hvv hvd hda hdh hdv hdd\n",
      "vaa vah vav vad vha vhh vhv vhd\n",
      "vva vvh vvv vvd vda vdh vdv vdd\n",
      "daa dah dav dad dha dhh dhv dhd\n",
      "dva dvh dvv dvd dda ddh ddv ddd\n"
     ]
    }
   ],
   "source": [
    "# 3rd level of decomposition:\n",
    "print(len(wp.get_level(3)))\n",
    "paths = [node.path for node in wp.get_level(3)]\n",
    "for i, path in enumerate(paths):\n",
    "    if (i+1) % 8 == 0:\n",
    "        print(path)\n",
    "    else:\n",
    "        print(path, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "d1e8ad25-47f5-4482-be2d-a5ec8cb30686",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]]\n"
     ]
    }
   ],
   "source": [
    "# Reconstructing data from Wavelet Packets\n",
    "# Let’s create a new empty 2D Wavelet Packet structure and set its nodes values with known data from the previous examples:\n",
    "new_wp = pywt.WaveletPacket2D(data=None, wavelet='db1', mode='symmetric')\n",
    "new_wp['vh'] = wp['vh'].data # [[0.0, 0.0], [0.0, 0.0]]\n",
    "new_wp['vv'] = wp['vh'].data # [[0.0, 0.0], [0.0, 0.0]]\n",
    "new_wp['vd'] = [[0.0, 0.0], [0.0, 0.0]]\n",
    "new_wp['a'] = [[3.0, 7.0, 11.0, 15.0], [3.0, 7.0, 11.0, 15.0], [3.0, 7.0, 11.0, 15.0], [3.0, 7.0, 11.0, 15.0]]\n",
    "new_wp['d'] = [[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]]\n",
    "# For convenience, Node2D.data gets automatically extracted from the base Node2D object:\n",
    "new_wp['h'] = wp['h'] # all zeros\n",
    "# Note: just remember to not assign to the node.data parameter directly (todo).\n",
    "# And reconstruct the data from the a, d, vh, vv, vd and h packets (Note that va node was not set and the WP tree is “not complete” - the va branch will be treated as zero-array):\n",
    "print(new_wp.reconstruct(update=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "71495ae1-c7cf-43bf-9e1b-277fc3489e36",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]]\n"
     ]
    }
   ],
   "source": [
    "# Now set the va node with the known values and do the reconstruction again:\n",
    "new_wp['va'] = wp['va'].data # [[-2.0, -2.0], [-2.0, -2.0]]\n",
    "print(new_wp.reconstruct(update=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "99df4cec-e835-4080-98a6-0d5469727804",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]\n",
      " [1.5 1.5 3.5 3.5 5.5 5.5 7.5 7.5]]\n"
     ]
    }
   ],
   "source": [
    "# which is just the same as the base sample data x.\n",
    "# Of course we can go the other way and remove nodes from the tree. If we delete the va node, again, we get the “not complete” tree from one of the previous examples:\n",
    "del new_wp['va']\n",
    "print(new_wp.reconstruct(update=False))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "a46fd6ec-3128-45d1-a660-53952353fa87",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "# Just restore the node before next examples.\n",
    "new_wp['va'] = wp['va'].data\n",
    "# If the update param in the WaveletPacket2D.reconstruct() method is set to False, the node’s Node2D.data attribute will not be updated.\n",
    "print(new_wp.data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "f285d471-9749-45b8-8e29-798c3701b927",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]]\n"
     ]
    }
   ],
   "source": [
    "# Otherwise, the WaveletPacket2D.data attribute will be set to the reconstructed value.\n",
    "print(new_wp.reconstruct(update=True))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "576c76cf-b7c4-4173-bb2b-32977db18824",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]\n",
      " [1. 2. 3. 4. 5. 6. 7. 8.]]\n"
     ]
    }
   ],
   "source": [
    "print(new_wp.data)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "f386230d-53a6-476f-b842-2df790b3ffb0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['a', 'h', 'va', 'vh', 'vv', 'vd', 'd']\n"
     ]
    }
   ],
   "source": [
    "print([n.path for n in new_wp.get_leaf_nodes()])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "071f3d6e-d174-4122-9fb6-aafad0ad85c6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "aaa aah aav aad aha ahh ahv ahd\n",
      "ava avh avv avd ada adh adv add\n",
      "haa hah hav had hha hhh hhv hhd\n",
      "hva hvh hvv hvd hda hdh hdv hdd\n",
      "vaa vah vav vad vha vhh vhv vhd\n",
      "vva vvh vvv vvd vda vdh vdv vdd\n",
      "daa dah dav dad dha dhh dhv dhd\n",
      "dva dvh dvv dvd dda ddh ddv ddd\n"
     ]
    }
   ],
   "source": [
    "paths = [n.path for n in new_wp.get_leaf_nodes(decompose=True)]\n",
    "len(paths)\n",
    "for i, path in enumerate(paths):\n",
    "    if (i+1) % 8 == 0:\n",
    "         print(path)\n",
    "    else:\n",
    "        try:\n",
    "            print(path, end=' ')\n",
    "        except:\n",
    "            print(path, end=' ')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "2a1b466f-585e-4196-a068-4ba32c99ab80",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "None\n"
     ]
    }
   ],
   "source": [
    "# Lazy evaluation\n",
    "x = numpy.array([[1, 2, 3, 4, 5, 6, 7, 8]] * 8)\n",
    "wp = pywt.WaveletPacket2D(data=x, wavelet='db1', mode='symmetric')\n",
    "# 1. At first the wp’s attribute a is None\n",
    "print(wp.a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "62dab270-43c9-4aea-8606-f4465a46cfd7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a: [[ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]]\n"
     ]
    }
   ],
   "source": [
    "# 2. During the first attempt to access the node it is computed via decomposition of its parent node (the wp object itself).\n",
    "print(wp['a'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "2336ea2d-f587-4317-a081-fd30f7601465",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a: [[ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]\n",
      " [ 3.  7. 11. 15.]]\n"
     ]
    }
   ],
   "source": [
    "# 3. Now the a is set to the newly created node:\n",
    "print(wp.a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "fcc47280-a2d7-45a0-8d41-8709d1b7d29c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "d: [[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "# And so is wp.d:\n",
    "print(wp.d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "308b365d-52e2-48c9-9888-ec8267b310fb",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
